package com.cloudkinto.service.product.impl;

import com.cloudkinto.common.PDFBuilder;
import com.cloudkinto.common.PageSize;
import com.cloudkinto.common.common.DateUtils;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.ProductInfoDao;
import com.cloudkinto.entity.ProductInfoDo;
import com.cloudkinto.service.file.FileService;
import com.cloudkinto.service.product.ProductBarCodeService;
import com.cloudkinto.service.product.vo.BarCodeItem;
import com.cloudkinto.service.product.vo.BarCodePrintReq;
import com.cloudkinto.service.product.vo.ProductInfoDetailRes;
import com.cloudkinto.service.product.vo.ProductInitRes;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author zhujiale
 * @description
 * @date 2022/11/15
 */
@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
public class ProductBarCodeServiceImpl implements ProductBarCodeService {
    @Autowired
    private FileService fileService;
    @Autowired
    private ProductInfoDao dao;


    @Value("${gbc.uploadPath.filePathTemp}")
    private String filePathTemp;
    //真正的存储路径
    @Value("${gbc.uploadPath.filePath}")
    private String filePath;

    private static Configuration freemarkerCfg = null;

    @Override
    public SingleResult operatingTypeInit() {
        Map<Long,String> map = new HashMap();
//        map.put(1L, "30*20");
//        map.put(2L, "40*30");
//        map.put(3L, "50*30");
//        map.put(4L, "60*40");
//        map.put(5L, "80*50");
//        map.put(6L, "100*70");
//        map.put(7L, "100*100");
//        map.put(8L, "100*150");
//        map.put(9L, "210*297");

        map.put(1L, "40*20");
        map.put(2L, "50*30");
        map.put(3L, "70*30");
        map.put(4L, "80*60");
        map.put(5L, "100*100");
        map.put(6L, "210*297");

        List<ProductInitRes> resList = new ArrayList<>();
        Iterator<Map.Entry<Long, String>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, String> it = iterator.next();
            ProductInitRes res = new ProductInitRes();
            res.setId(it.getKey());
            res.setName(it.getValue());
            resList.add(res);
        }

        return SingleResult.success(resList);
    }

    @Override
    public SingleResult getDetail(Long id) {
        ProductInfoDo productInfoDo = dao.selectById(id);
        ProductInfoDetailRes res = new ProductInfoDetailRes();
        BeanUtils.copyProperties(productInfoDo, res);
        res.setDate(DateUtils.dateFormatToString(new Date(), null));
        res.setMadeInChina("Made IN China");
        return SingleResult.success(res);
    }

    @Override
    public SingleResult barCodePrint(BarCodePrintReq req,Long userId) throws TemplateException, IOException, DocumentException {
        //根据操作类型选择需要打印的纸张尺寸
        Rectangle pageSize = getPageSizeByType(req.getOperateType());

        List<BarCodeItem> list = new ArrayList<>();
        req.getCodeAndNumList().forEach(et ->{
            //只有a4纸数量会正常 其他纸 会少一个 所以此处处理一下
            int num;
            if (req.getOperateType() == 9) {
                num = et.getNumber();
            }else {
                num = et.getNumber() + 1;
            }
            for (int i = 0; i < num; i++) {
                BarCodeItem item = new BarCodeItem();
                String barCodeUrl = fileService.getFilePathTemp(et.getBarCodeId());
                System.err.println(barCodeUrl);
                if (StringUtils.isNotBlank(barCodeUrl)) {
                    item.setImageUrl(barCodeUrl);
                }
                list.add(item);
            }
        });
        Map<String, Object> data = new HashMap();
        data.put("image", list);
        data.put("height", req.getHeight());
        data.put("width", req.getWidth());


        //解析的ftm文件名，具体路径在【freemarkerCfg】方法中进行定义
        final String htmlTmp = "bar_code.ftl";
        //生成的pdf模板存放的位置【服务器本地盘下 tempfile文件夹下】
        String fileName = "条形码" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".pdf";
        final String pdftemp = filePathTemp + File.separator + fileName;
        // 获取模板,并设置编码方式
        freemarkerCfg = new Configuration();
        try {
            freemarkerCfg.setDirectoryForTemplateLoading(new File(filePathTemp).getCanonicalFile());
        } catch (IOException e) {
            e.printStackTrace();
        }
        Template template = freemarkerCfg.getTemplate(htmlTmp);
        template.setEncoding("UTF-8");
        StringWriter out = new StringWriter();
        // 合并模板跟数据
        template.process(data, out);
        // htmlData 模板字符流
        String htmlData = out.toString();


        // 设置文档格式,数字边距
        Document document = new Document(pageSize, 0, 0, 0, 0);
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(pdftemp));
        // 添加页码
        PDFBuilder builder = new PDFBuilder();
        writer.setPageEvent(builder);
        // 打开文档
        document.open();
        XMLWorkerHelper.getInstance().parseXHtml(writer, document, new ByteArrayInputStream(htmlData.getBytes()), (InputStream) null);
        // 关闭文档
        document.close();

        //将/www/wwwroot/tempfile pdf上传到服务器
        InputStream is = new FileInputStream(pdftemp);
        Long fileId1 = fileService.uploadTempFile(fileName, is, userId);
        fileService.uploadFile(fileId1);
        //获取上传文件url
        return SingleResult.success(fileService.getFilePath(fileId1));
    }

    private Rectangle getPageSizeByType(Integer operateType) {
        Rectangle pageSize;
        switch (operateType) {
            case 1:
                pageSize = PageSize.LABEL_30_20;
                break;
            case 2:
                pageSize = PageSize.LABEL_40_30;
                break;
            case 3:
                pageSize = PageSize.LABEL_50_30;
                break;
            case 4:
                pageSize = PageSize.LABEL_60_40;
                break;
            case 5:
                pageSize = PageSize.LABEL_80_50;
                break;
            case 6:
                pageSize = PageSize.LABEL_100_70;
                break;
            case 7:
                pageSize = PageSize.LABEL_100_100;
                break;
            case 8:
                pageSize = PageSize.LABEL_100_150;
                break;
            case 9:
                pageSize = PageSize.A4;
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + operateType);
        }
        return pageSize;
    }


}
